import type { PageType } from '../../../../lib/page_handler/type'
import type { ComponentStyleIdType } from '../../../../types/interfaces'
import type { IBaiduNewsSearchParams, IBaiduWebSearchParams } from './platform/baidu'
import type { IGreasyForkUrlParams } from './platform/greasy_fork'
import { BaseModule } from '../../../../lib/abstract'
import { PageManager } from '../../../../lib/abstract/page_manager'
import { BodyHandler } from '../../../../lib/body_handler'
import { DocumentOperator } from '../../../../lib/document_operator'
import { ICON_COLOR, ICON_IDS } from '../../../../lib/icons/types/constants'
import { MessageAlert } from '../../../../lib/message_alert'
import { PageHandler } from '../../../../lib/page_handler'
import { BaiduPageType } from '../../../../lib/page_handler/platform/baidu/types'
import { ToolKit } from '../../../../lib/utils/toolkit'
import {
  ComponentStyleId,
  getAllHideSelector,
  HOSTNAME,
  logger,
  MODULE_CONFIG,
  SUPPORTED_PLATFORMS,
} from '../../../../types/constants'
import { SYMBOLS } from '../../../../types/interfaces'
import { ConfigManager } from '../../../config_manager'
import { PAGE_NUM_STYLES } from '../../appearance/style_enhancement/platforms'
import { AutoPaginationBaidu } from './platform/baidu'
import { AutoPaginationBian } from './platform/bian'
import { AutoPaginationGitee } from './platform/gitee'
import { AutoPaginationGithub } from './platform/github'
import { AutoPaginationGreasyFork } from './platform/greasy_fork'
import { AutoPaginationConfig } from './service/config'
import { PAGINATION_CONFIG } from './service/config/types'
import { AutoPaginationMessage } from './service/message'
import { AutoPaginationResult } from './service/result'

export enum IPaginationLoadType {
  Item = 'item',
  Pagination = 'pagination',
}

export enum IPaginationBatchLoadType {
  Full = 'full',
  Custom = 'custom',
}

export interface IPaginationSelectors {
  header?: string
  container: string
  item: string
}
export interface IPaginationOptions {
  selectors: ((instance: AutoPagination) => IPaginationSelectors) | IPaginationSelectors
  headerInsertPosition?: 'beforePageSeparator' | 'afterPageSeparator'
  pageNum: (instance: AutoPagination) => string
  pageItemLink: (instance: AutoPagination) => string
  nextPageUrl: (instance: AutoPagination, currentPage: number) => string | null
}

export type ISearchParams = undefined | IBaiduWebSearchParams | IBaiduNewsSearchParams | IGreasyForkUrlParams

interface Config {
  enabled?: boolean
}

/**
 * 测试链接：
 * 1）https://pic.netbian.com/new/
 * 2）https://greasyfork.org/zh-CN/scripts/462689/versions
 */
export class AutoPagination extends BaseModule {
  // @Decorators.Identity
  readonly id: string = 'auto_pagination'
  // @Decorators.PublicState
  isInitialized: boolean = false
  private readonly indicatorId: string = MODULE_CONFIG.COMPONENTS.pageLoader.id
  private static instance: AutoPagination
  // @Decorators.InheritedConfig
  readonly styleId: string = ComponentStyleId[this.name]
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  // @Decorators.CoreDependency
  readonly baiduService: AutoPaginationBaidu = AutoPaginationBaidu.getInstance()
  readonly greasyForkService: AutoPaginationGreasyFork = AutoPaginationGreasyFork.getInstance()
  readonly bianService: AutoPaginationBian = AutoPaginationBian.getInstance()
  readonly giteeService: AutoPaginationGitee = AutoPaginationGitee.getInstance()
  readonly githubService: AutoPaginationGithub = AutoPaginationGithub.getInstance()
  readonly configService: AutoPaginationConfig = AutoPaginationConfig.getInstance(this)
  private readonly messageService: AutoPaginationMessage = AutoPaginationMessage.getInstance(this.indicatorId)
  // @Decorators.Dependency
  private readonly messageAlert: MessageAlert = MessageAlert.getInstance()
  private readonly pageManager: PageManager = PageManager.getInstance()
  private readonly documentOperator = DocumentOperator.getInstance()
  // @Decorators.UIElement
  private readonly defaultPageNum: number = 1 // 默认页码
  private readonly defaultMaxPageNum: number = 100 // 默认最大页码数
  private readonly pageSeparatorClass: string = MODULE_CONFIG.COMPONENTS.pageSeparator.class
  private readonly batchProgressClass: string = 'batch-progress'
  private readonly batchActiveClass: string = 'batch-active'
  private readonly batchLoadingClass: string = 'batch-loading'
  // 默认每页结果数量
  get defaultResultNum(): number {
    return this.pageManager.getSearchResultNum()
  }

  // 最大页码数
  get maxPageNum(): number {
    switch (HOSTNAME) {
      case SUPPORTED_PLATFORMS.GREASY_FORK:
        return this.greasyForkService.getMaxPageNumFromPagination()
      case SUPPORTED_PLATFORMS.BIAN:
        return this.bianService.getMaxPageNumFromPagination()
      case SUPPORTED_PLATFORMS.GITEE:
        return this.giteeService.getMaxPageNumFromPagination()
      default:
        return this.defaultMaxPageNum
    }
  }

  // @Decorators.Core
  readonly pageType: PageType = PageHandler.getCurrentPageType()
  // @Decorators.Config
  currentConfig: IPaginationOptions = PAGINATION_CONFIG[HOSTNAME] || {
    selectors: {} as IPaginationSelectors,
    headerInsertPosition: 'beforePageSeparator',
    pageNum: (): string => '',
    pageItemLink: (): string => '',
    nextPageUrl: (): string | null => null,
  }

  selectors: IPaginationSelectors = typeof this.currentConfig.selectors === 'function'
    ? this.currentConfig.selectors(this)
    : this.currentConfig.selectors

  // 结果服务依赖选择器，所以需要在选择器初始化后创建
  private readonly resultService: AutoPaginationResult = AutoPaginationResult.getInstance(this)

  // @Decorators.TemporaryState
  private scrollHandler: ((this: Window) => void) | undefined
  currentPageNum: number = 0
  private isMaxPageNum: boolean = false
  private isLoading: boolean = false
  private _activePageEnd: boolean = false

  // 获取当前值
  get activePageEnd(): boolean {
    return this._activePageEnd
  }

  // 滚动相关
  private scrollEndTimeout?: number
  private scrollRestoreDelay: number = 2000 // 2秒
  private scrollMaxDisabledTime: number = 3 * 60 * 1000 // 3分钟
  private lastScrollDirection: 'up' | 'down' | null = null
  private scrollDirectionCount = 0
  private lastValidScrollTime = 0
  // 加载全部
  private isLoadingAll: boolean = false
  private loadedPages: Set<number> = new Set()
  private totalPagesToLoad: number = 0
  private pageLoadedStatus: Map<number, boolean> = new Map()
  // 强制结束
  private forceCancelBatch: boolean = false
  private forceCancelRestoreDelay: number = 5000
  private forceCancelTimeout?: number
  // 隐藏
  private hideProgressDelay: number = 2000

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'AutoPagination'
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): AutoPagination {
    if (!AutoPagination.instance) {
      AutoPagination.instance = new AutoPagination()
    }
    return AutoPagination.instance
  }

  handleCleanupEventListeners(): void {
    if (this.scrollHandler) {
      window.removeEventListener('scroll', this.scrollHandler)
    }
  }

  handleCleanupCreatedElements(): void {
    this.removeLoadingIndicator()
    this.clearAllSeparators()
  }

  handleCleanupStyles(): void {
    this.unregisterStyle(this.styleId)
  }

  handleCleanupReferences(): void {
    this.currentPageNum = 0
    this.isLoading = false
    this.activePageEnd = false

    if (this.scrollEndTimeout) {
      clearTimeout(this.scrollEndTimeout)
    }
  }

  handleCleanupOthers(): void {
    this.cancelBatchLoad(false) // 取消进行中的批量加载
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.applyPagination()
    this.applyStyles()

    this.registerStyle(this.styleId, this.getStyles())
  }

  /**
   * 应用分页样式
   */
  applyStyles(): void {
    Object.entries(PAGE_NUM_STYLES).forEach(([platform, StyleClass]) => {
      if (platform === HOSTNAME) {
        StyleClass?.getInstance().handlePageNumStyle()
      }
    })
  }

  // 设置值并触发监听
  set activePageEnd(value: boolean) {
    const oldValue = this._activePageEnd

    if (oldValue !== value) {
      logger.debug(`[${this.name}] activePageEnd 变化: ${oldValue} -> ${value}`)

      this._activePageEnd = value
      this.onActivePageEndChanged(value, oldValue)
    }
  }

  /**
   * 内部处理变化逻辑
   */
  private onActivePageEndChanged(_newValue: boolean, _oldValue: boolean): void {
    this.updateScrollButton()
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  applyPagination(): void {
    if (!this.checkPage())
      return

    this.initPageSeparator()
    this.initScrollHandler()
  }

  checkPage(): boolean {
    switch (HOSTNAME) {
      case SUPPORTED_PLATFORMS.BAI_DU:
        return this.baiduService.checkPage()
      case SUPPORTED_PLATFORMS.GREASY_FORK:
        return this.greasyForkService.checkPage()
      case SUPPORTED_PLATFORMS.BIAN:
        return this.bianService.checkPage()
      default:
        return true
    }
  }

  generateUrlParams(linkParams: IBaiduWebSearchParams | IBaiduNewsSearchParams, searchKeyword: string, currentPage: number): Partial<Record<keyof IBaiduWebSearchParams, string>> | Record<keyof IBaiduNewsSearchParams, string> | undefined {
    if (HOSTNAME === SUPPORTED_PLATFORMS.BAI_DU) {
      return this.pageType === BaiduPageType.Web
        ? this.baiduService.generateBaiduWebSearchParams(linkParams as IBaiduWebSearchParams, searchKeyword, currentPage)
        : this.baiduService.generateBaiduNewsSearchParams(linkParams as IBaiduNewsSearchParams, searchKeyword, currentPage)
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.GREASY_FORK) {
      return undefined
    }
  }

  /**
   * 初始化分页分隔符
   */
  initPageSeparator(): void {
    const pageNum = this.getCurrentPageNum(this.configService.getPageLoadType())

    this.addPageSeparator(pageNum, 'prepend')
    this.currentPageNum = pageNum
  }

  /**
   * 初始化滚动监听
   */
  private initScrollHandler(): void {
    let lastScrollPosition = 0
    const scrollThreshold = 100 // 滚动阈值(px)

    const handler = async () => {
      // 跳过滚动到底部触发的滚动
      if (this.activePageEnd)
        return

      // 1. 检查文档高度是否足以滚动
      const canScroll = BodyHandler.checkScrollable()

      if (!canScroll)
        return

      // 2. 正常滚动检测逻辑
      const currentPosition = window.scrollY
      const currentTime = Date.now()
      // 检测滚动方向
      const isScrollingDown = this.detectScrollDirection(currentPosition, lastScrollPosition)
      // 只有在持续向下滚动时才检查底部
      const isNearBottom = this.isNearBottom(scrollThreshold)

      if (isScrollingDown && isNearBottom && !this.isLoading && this.scrollDirectionCount >= 2 && currentTime - this.lastValidScrollTime > 300) {
        this.lastValidScrollTime = currentTime
        this.currentPageNum += 1

        if (this.currentPageNum === 1)
          return

        await this.loadNextPage(this.currentPageNum)
      }

      lastScrollPosition = currentPosition
    }

    this.scrollHandler = ToolKit.func.throttle(handler, 200)

    window.addEventListener('scroll', this.scrollHandler)
  }

  /**
   * 检测滚动方向
   */
  private detectScrollDirection(current: number, last: number): boolean {
    const delta = current - last
    const absDelta = Math.abs(delta)

    // 忽略微小滚动（小于3px）
    if (absDelta < 3) {
      return this.lastScrollDirection === 'down'
    }

    if (delta > 0) {
      this.scrollDirectionCount = Math.min(this.scrollDirectionCount + 1, 5)
      this.lastScrollDirection = 'down'
    }
    else {
      this.scrollDirectionCount = Math.max(this.scrollDirectionCount - 1, -5)
      this.lastScrollDirection = 'up'
    }

    return this.lastScrollDirection === 'down'
  }

  /**
   * 加载下一页
   */
  private async loadNextPage(pageNum: number): Promise<void> {
    this.currentPageNum = pageNum

    // 检查是否已加载到最大页码
    if (this.isMaxPageNum || pageNum > this.maxPageNum) {
      this.messageService.showMaxLoadedMessage(this.maxPageNum)
      this.diableScrollLoad()
      return
    }

    this.messageService.showLoadingMessage(this.currentPageNum)

    try {
      const nextPageUrl = this.currentConfig.nextPageUrl(this, pageNum)

      if (!nextPageUrl) {
        logger.warn(`[${this.name}] 下一页（${pageNum}）加载 URL 未获取到`)
        return
      }

      logger.important(`[${this.name}] 加载下一页（${pageNum}）`, nextPageUrl)
      const newResults = await this.fetchNextPage(nextPageUrl)

      // 等待结果插入完成
      await this.appendResultsAndWait(newResults)
    }
    catch (error: any) {
      logger.error(`[${this.name}] 下一页（${pageNum}）翻页失败`, error)
    }
    finally {
      this.isLoading = false
      this.removeLoadingIndicator()
    }
  }

  /**
   * 加载单页
   */
  private async loadSinglePage(pageNum: number): Promise<boolean> {
    this.currentPageNum = pageNum

    // 检查是否已加载到最大页码
    if (this.isMaxPageNum || pageNum > this.maxPageNum) {
      this.messageService.showMaxLoadedMessage(this.maxPageNum)
      return false
    }

    this.messageService.showLoadingMessage(this.currentPageNum)

    try {
      const nextPageUrl = this.currentConfig.nextPageUrl(this, pageNum)

      if (!nextPageUrl) {
        logger.warn(`[${this.name}] 第 ${pageNum} 页加载 URL 未获取到，当前域名：${HOSTNAME}`)
        return false
      }

      logger.important(`[${this.name}] 加载第 ${pageNum} 页`, nextPageUrl)
      const newResults = await this.fetchNextPage(nextPageUrl)

      if (newResults && newResults.documentElement) {
        await this.appendResultsAndWait(newResults)
        return true
      }

      return false
    }
    catch (error: any) {
      logger.error(`[${this.name}] 第 ${pageNum} 页加载失败`, error)
      return false
    }
    finally {
      this.removeLoadingIndicator()
    }
  }

  /**
   * 加载所有页
   */
  private async loadAllPages(): Promise<void> {
    if (this.isLoadingAll) {
      return
    }

    // 重置分页状态
    this.pageLoadedStatus.clear()
    // 重置强制结束标识
    this.forceCancelBatch = false
    // 重置已加载页集合
    this.loadedPages.clear()
    // 更新加载状态
    this.updateLoadAllStatus(true)

    // 获取总页数
    const customPageNum = this.pageManager.getPageNum()
    const startPage = this.currentPageNum
    this.totalPagesToLoad = customPageNum ? customPageNum + this.currentPageNum : this.maxPageNum - 1
    const startPageIndex = this.currentPageNum + 1
    let endPageIndex = this.totalPagesToLoad + 1

    if (startPageIndex === this.maxPageNum) {
      endPageIndex = this.maxPageNum

      logger.attention(`[${this.name}] 加载最后一页 （第 ${endPageIndex} 页）`)
    }
    else {
      logger.attention(`[${this.name}] 开始加载所有页（第 ${startPageIndex} 页到第 ${endPageIndex} 页）`)
    }

    try {
      // 显示进度指示器
      this.showProgressOnSeparator(0, this.totalPagesToLoad, startPage)

      // 从当前页的下一页开始加载
      for (let pageNum = startPageIndex; pageNum <= endPageIndex; pageNum++) {
        // 检查强制结束标识
        if (this.forceCancelBatch) {
          logger.info(`[${this.name}] 用户取消了批量加载`)
          break
        }

        // 更新进度
        this.showProgressOnSeparator(pageNum - startPage, this.totalPagesToLoad, startPage)

        try {
          const status = this.checkPageLoadStatus(pageNum)
          this.pageLoadedStatus.set(pageNum, status)

          if (!status) {
            this.loadedPages.add(pageNum)
            await this.loadSinglePage(pageNum)

            // 添加小延迟避免请求过于频繁
            await ToolKit.async.delay(500)
          }
          else {
            logger.info(`[${this.name}] 第 ${pageNum} 页存在分页分隔符，跳过加载`)
          }
        }
        catch (error) {
          logger.warn(`[${this.name}] 第 ${pageNum} 页加载失败:`, error)
          // 继续加载下一页
          // continue
        }
      }

      if (this.forceCancelBatch)
        return

      if (this.checkPageHasLoadedAllPage() && this.checkPageHasLoadedMaxPage()) {
        this.messageService.showHasLoadedMessage()
      }
      else {
        this.messageService.showCompletionMessage(this.loadedPages.size)
      }
    }
    catch (error: any) {
      logger.error(`[${this.name}] 批量加载失败:`, error)
      this.messageService.showErrorMessage('批量加载过程中发生错误')
    }
    finally {
      this.updateLoadAllStatus(false)
      ToolKit.async.delay(this.hideProgressDelay).then(() => {
        this.hideProgressOnSeparator()
      })
    }
  }

  /*
   * 更新加载状态
   */
  updateLoadAllStatus(enabled: boolean): void {
    this.isLoadingAll = enabled

    // 更新加载所有按钮状态
    this.updateLoadAllButton()
  }

  /**
   * 是否自定义加载页数
   */
  private shouldCustomPageNum(): boolean {
    return this.pageManager.getPageNum() !== 0
  }

  /**
   * 检查分页状态
   */
  private checkPageLoadStatus(pageNum: number): boolean {
    return $(`.${this.pageSeparatorClass}.page-${pageNum}`).length > 0
  }

  /**
   * 检查是否已全部加载
   */
  private checkPageHasLoadedAllPage(): boolean {
    return Array.from(this.pageLoadedStatus.values()).every(v => v)
  }

  /**
   * 检查是否已加载最大页码
   */
  private checkPageHasLoadedMaxPage(): boolean {
    return this.checkPageLoadStatus(this.maxPageNum)
  }

  /**
   * 获取下一页内容
   */
  private async fetchNextPage(url: string): Promise<Document> {
    // 静默跳过并发请求
    if (this.isLoading) {
      return new Promise(() => {}) // 返回永远 pending 的Promise
    }

    this.isLoading = true

    try {
      const result = await this.documentOperator.fetchDocument({
        url,
      })

      const doc: Document = result.data || document
      const selector: string = this.selectors.item

      // 验证内容有效性
      if (doc && $(selector, doc).length > 0)
        return doc

      logger.notice(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 没有更多内容了`, selector)
      return document // 返回空文档避免中断流程
    }
    catch (error) {
      logger.warn(`[${this.name}] 文档获取失败:`, error)
      return document // 返回空文档
    }
    finally {
      this.isLoading = false
    }
  }

  /**
   * 追加新结果
   */
  private async appendResultsAndWait(newDoc: Document, unique: boolean = true): Promise<void> {
    const startTime = Date.now()
    const pageNum = this.currentPageNum

    try {
      // 先设置插入状态为 pending
      this.resultService.setInsertionState(pageNum, {
        status: 'pending',
        totalItems: 0,
        insertedItems: 0,
        startTime,
      })

      // 开始插入
      this.resultService.appendResults(pageNum, newDoc, unique)

      // 等待插入完成
      const finalState = await this.resultService.waitForInsertionComplete(pageNum)

      const duration = Date.now() - startTime

      logger.debug(`[${this.name}] 第 ${pageNum} 页插入完成`, {
        status: finalState.status,
        inserted: finalState.insertedItems,
        total: finalState.totalItems,
        duration: `${duration}ms`,
      })

      if (finalState.status === 'failed') {
        throw new Error(`第 ${pageNum} 页插入失败`)
      }
    }
    catch (error: any) {
      const duration = Date.now() - startTime
      logger.error(`[${this.name}] 第 ${pageNum} 页等待插入完成失败，耗时 ${duration} ms`, error)
      throw error
    }
  }

  /**
   * 获取平台当前的页码
   */
  private getCurrentPageNum(type: IPaginationLoadType): number {
    try {
      let pageNum

      if (type === IPaginationLoadType.Item) {
        // 1. 精确选择目标的第一个元素（排除隐藏项）
        const $targetItem = $(`${this.selectors.item}:not(${getAllHideSelector()})`).first()

        // 2. 安全获取ID数值
        const itemId = Number.parseInt($targetItem.attr('id') || '', this.defaultResultNum)

        if (Number.isNaN(itemId) || itemId <= 0) {
          logger.warn(`[${this.name}] 无效的结果项 id 属性（${itemId}）, 返回默认页码 ${this.defaultPageNum}`)
          return this.defaultPageNum
        }

        // 3. 计算页码（向上取整）
        pageNum = Math.max(1, Math.ceil(Number(itemId) / this.defaultResultNum))
      }
      else {
        const targetSelector = `${this.configService.getPageNumSelector()}`
        const $targetItem = $(targetSelector).first()

        if (!$targetItem || $targetItem.length === 0) {
          logger.warn(`[${this.name}] 未找到分页元素, 返回默认页码 ${this.defaultPageNum}`, targetSelector)
          return this.defaultPageNum
        }

        const content = $targetItem.text()
        const pageNumContent = Number.parseInt(content || '', this.defaultResultNum)

        if (Number.isNaN(pageNumContent) || pageNumContent <= 0) {
          logger.warn(`[${this.name}] 无效的页码文本（${content}）, 返回默认页码 ${this.defaultPageNum}`)
          return this.defaultPageNum
        }

        pageNum = Math.max(1, Number(pageNumContent))
      }

      logger.attention(`[${this.name}] 当前页码: ${pageNum}，最大页码: ${this.maxPageNum}`)

      // 4. 检查是否已加载到最大页码
      if (pageNum === this.maxPageNum) {
        this.isMaxPageNum = true
      }

      return pageNum
    }
    catch (error) {
      logger.warn(`[${this.name}] 页码解析失败`, error)
      return 1 // 异常时返回安全值
    }
  }

  /**
   * 添加分页分隔符
   */
  addPageSeparator(
    pageNum: number,
    position: 'prepend' | 'append' = 'append',
  ): JQuery<HTMLElement> {
    let $separator = $(`#mbf-separator-${pageNum}.${this.pageSeparatorClass}`)

    if ($separator && $separator.length > 0)
      return $separator

    $separator = $(`
      <div id="mbf-separator-${pageNum}" class="${this.pageSeparatorClass} page-${pageNum}">
        <div class="mbf-page-nav">
          <span class="mbf-page-scroll ${this.activePageEnd ? 'disabled' : ''}" title="${this.getScrollStatusTitle(this.activePageEnd)}"></span>
          <span class="mbf-page-number" data-page="${pageNum}">
            <b>第 <span>${pageNum}</span> 页</b>
          </span>
          <span class="page-link mbf-page-top" title="返回顶部"></span>
          <span class="page-link mbf-page-prev" title="上一页"></span>
          <span class="page-link mbf-page-next" title="下一页"></span>
          <span class="page-link mbf-page-end" title="最后一页"></span>
          <span class="page-link mbf-page-more" title="加载更多"></span>
          <span class="page-link mbf-page-all ${this.getBatchLoadType()}" title="${this.getBatchLoadTitle()}"></span>
        </div>
      </div>
    `)

    const insertSelector = this.selectors.header || this.selectors.container

    if (position === 'prepend') {
      $separator.prependTo(insertSelector)
    }
    else {
      $separator.appendTo(insertSelector)
    }

    this.bindPageNavEvents($separator)
    ToolKit.browser.platform.markProjectElement($separator)

    return $separator
  }

  /**
   * 获取滚动加载状态标题
   */
  private getScrollStatusTitle(enable: boolean): string {
    return !enable ? '支持滚动加载（点击关闭）' : '不支持滚动加载（点击开启）'
  }

  /**
   * 获取批量加载类型
   */
  private getBatchLoadType(): IPaginationBatchLoadType {
    if (!this.shouldCustomPageNum()) {
      return IPaginationBatchLoadType.Full // 完整加载
    }

    return IPaginationBatchLoadType.Custom // 自定义加载
  }

  /**
   * 获取批量加载的标题文本
   */
  private getBatchLoadTitle(): string {
    if (!this.shouldCustomPageNum()) {
      return '加载所有'
    }

    const customPageNum = this.pageManager.getPageNum()
    const loadType = this.getBatchLoadType()

    switch (loadType) {
      default:
        return `加载 ${customPageNum} 页`
    }
  }

  /**
   * 绑定分页导航事件
   */
  private bindPageNavEvents($separator: JQuery<HTMLElement>): void {
    $separator.find('.mbf-page-scroll')?.on('click', () => {
      this.handleScrollButton()
    })

    $separator.find('.mbf-page-top')?.on('click', () => {
      this.handleToPageTop()
    })

    $separator.find('.mbf-page-prev')?.on('click', (e) => {
      const pageNum = this.getSeparatorPageNum(e)

      if (pageNum === 2) {
        this.handleToPageTop()
      }
      else {
        this.jumpToPage(pageNum - 1)
      }
    })

    $separator.find('.mbf-page-next')?.on('click', (e) => {
      const pageNum = this.getSeparatorPageNum(e)

      if (!this.isSeparatorExist(pageNum + 1))
        return

      this.jumpToPage(pageNum + 1)
    })

    $separator.find('.mbf-page-end')?.on('click', () => {
      this.jumpToPage(this.currentPageNum)
    })

    $separator.find('.mbf-page-more')?.on('click', async () => {
      await this.loadNextPage(this.currentPageNum + 1)
    })

    $separator.find('.mbf-page-all')?.on('click', async (e) => {
      const $element = $(e.currentTarget)
      const $activeSeparator = $element.closest(`.${this.pageSeparatorClass}`)

      if (this.currentPageNum + 1 > this.maxPageNum) {
        this.diableScrollLoad()
        this.messageService.showMaxLoadedMessage(this.maxPageNum)
        this.hideProgressOnSeparator()

        logger.important(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 已全部加载完成，跳过加载`)
        return
      }

      if (this.isLoadingAll) {
        // 如果正在加载，点击则取消
        this.cancelBatchLoad()
      }
      else {
        // 添加活动类
        $activeSeparator.addClass(this.batchActiveClass)
        // 如果未加载，开始加载
        await this.loadAllPages()
      }
    })
  }

  /**
   * 更新滚动加载按钮的状态
   */
  updateScrollButton(): void {
    $(`.${this.pageSeparatorClass}`)
      ?.find('.mbf-page-scroll')
      .attr('title', this.getScrollStatusTitle(this.activePageEnd))
      .toggleClass('disabled', this.activePageEnd)
  }

  /**
   * 更新加载所有按钮的显示
   */
  updateLoadAllButton(): void {
    $(`.${this.pageSeparatorClass}`)
      ?.find('.mbf-page-all')
      .removeClass(`${Object.values(IPaginationBatchLoadType).join(' ')}`)
      .addClass(this.getBatchLoadType())
      .attr('title', this.isLoadingAll ? '取消批量加载' : this.getBatchLoadTitle())
      .toggleClass(this.batchLoadingClass, this.isLoadingAll)
  }

  /**
   * 获取当前点击元素的页码
   */
  getSeparatorPageNum(e: JQuery.ClickEvent): number {
    const $element = $(e.currentTarget)
    const $container = $element.closest('.mbf-page-nav')
    return $container.find('.mbf-page-number').data('page')
  }

  /**
   * 检查分隔符元素是否存在
   */
  isSeparatorExist(pageNum: number): boolean {
    const $separator = $(`#mbf-separator-${pageNum}`)
    return $separator && $separator.length > 0
  }

  handleScrollButton(): void {
    this.activePageEnd = !this.activePageEnd
  }

  handleToPageTop(): void {
    window.scrollTo({ top: 0, behavior: 'smooth' })
  }

  /**
   * 跳转指定页
   */
  private jumpToPage(pageNum: number): void {
    const target = document.getElementById(`mbf-separator-${pageNum}`)
    const header = document.getElementById('head')

    if (!target)
      return

    this.activePageEnd = true

    // 计算预留高度（未包含安全边距）
    const headerHeight = header ? header.offsetHeight : 70
    const targetRect = target.getBoundingClientRect()
    const scrollPosition = window.scrollY + targetRect.top - headerHeight

    window.scrollTo({
      top: scrollPosition,
      behavior: 'smooth',
    })

    this.enableScrollLoad()
  }

  /**
   * 禁用滚动加载
   */
  diableScrollLoad(delay?: number): void {
    const diableDelay = delay || this.scrollMaxDisabledTime
    this.activePageEnd = true

    clearTimeout(this.scrollEndTimeout)

    this.scrollEndTimeout = window.setTimeout(() => {
      this.activePageEnd = false
    }, diableDelay)

    logger.notice(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 禁用滚动加载，延迟 ${diableDelay}ms`)
  }

  /**
   * 启用滚动加载
   */
  enableScrollLoad(delay?: number): void {
    clearTimeout(this.scrollEndTimeout)

    this.scrollEndTimeout = window.setTimeout(() => {
      this.activePageEnd = false
    }, delay || this.scrollRestoreDelay)
  }

  /**
   * 检查是否接近底部
   */
  private isNearBottom(threshold: number): boolean {
    if (!BodyHandler.checkScrollable())
      return true

    const { scrollHeight, clientHeight } = document.documentElement
    const currentPosition = window.scrollY
    const distanceToBottom = scrollHeight - clientHeight - currentPosition

    // 只有向下滚动时才检测接近底部
    return distanceToBottom < threshold && this.scrollDirectionCount > 0
  }

  /**
   * 无更多内容的处理逻辑
   */
  handleNoMoreContent(): void {
    this.currentPageNum = Math.max(1, this.currentPageNum - 1) // 回退页码

    // 显示提示
    this.messageService.showNoResultMessage()

    // 禁用后续滚动加载
    this.diableScrollLoad()
  }

  /**
   * 在分隔符上显示进度
   */
  private showProgressOnSeparator(current: number, total: number, startPage: number): void {
    const percentage = Math.round((current / total) * 100)

    // 找到当前激活的分隔符
    const $separator = $(`#mbf-separator-${startPage}`)

    if ($separator.length === 0)
      return

    // 1. 更新分隔符底部边框（进度条效果）
    this.updateSeparatorProgressBar($separator, percentage)

    // 2. 更新加载所有按钮的伪元素显示进度
    this.updateLoadAllButtonProgress($separator, current, total, percentage)
  }

  /**
   * 更新分隔符底部边框进度条
   */
  private updateSeparatorProgressBar($separator: JQuery<HTMLElement>, percentage: number): void {
    // 移除可能存在的旧进度条样式
    $separator.removeClass('progress-0 progress-25 progress-50 progress-75 progress-100')

    // 根据进度添加对应的类名
    let progressClass = 'progress-0'

    if (percentage >= 100)
      progressClass = 'progress-100'
    else if (percentage >= 75)
      progressClass = 'progress-75'
    else if (percentage >= 50)
      progressClass = 'progress-50'
    else if (percentage >= 25)
      progressClass = 'progress-25'

    $separator.addClass(progressClass)

    // 直接设置 CSS 变量控制进度
    $separator.css('--progress-percentage', `${percentage}%`)
  }

  /**
   * 更新加载所有按钮的进度显示
   */
  private updateLoadAllButtonProgress($separator: JQuery<HTMLElement>, current: number, total: number, percentage: number): void {
    const $loadAllButton = $separator.find('.mbf-page-all')

    if ($loadAllButton.length === 0)
      return

    // 使用伪元素显示进度文本
    $loadAllButton
      .attr('data-progress', `${percentage}% 【${current.toString().padStart(2, '0')}/${total.toString().padStart(2, '0')}】`)
      .addClass('show-progress')
  }

  /**
   * 取消批量加载
   */
  private cancelBatchLoad(showMessage: boolean = true): void {
    this.forceCancelBatch = true
    this.isLoadingAll = false

    // 设置强制结束标识的自动重置
    if (this.forceCancelTimeout) {
      clearTimeout(this.forceCancelTimeout)
    }
    this.forceCancelTimeout = window.setTimeout(() => {
      this.forceCancelBatch = false
      logger.info(`[${this.name}] 强制结束标识已重置`)
    }, this.forceCancelRestoreDelay)

    if (showMessage)
      this.messageService.showCancelMessage(this.loadedPages.size)

    this.hideProgressOnSeparator()
  }

  /**
   * 隐藏分隔符上的进度显示
   */
  private hideProgressOnSeparator(): void {
    $(`.${this.pageSeparatorClass}.${this.batchActiveClass}`)
      ?.removeClass(this.batchActiveClass)
      .find(`.${this.batchProgressClass}`)
      ?.remove()
  }

  /**
   * 移除加载指示器
   */
  private removeLoadingIndicator(): void {
    $(`#${this.indicatorId}`)?.remove()
  }

  /**
   * 清除所有分页分隔符
   */
  private clearAllSeparators(): void {
    $(`.${this.pageSeparatorClass}`).remove()
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.applyPagination()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  /**
   * 获取分页分隔符的外边距
   */
  getMargin(): string {
    switch (HOSTNAME) {
      case SUPPORTED_PLATFORMS.BAI_DU:
        return `5px 0 ${this.themeVarService.search.resultItem.gap} var(--scrollbar-offset)`
      default:
        return '5px 0'
    }
  }

  getStyles(): string {
    return `
#mbf-separator-1 {
  margin-top: 0 !important;
}

/* 分页分隔符样式 */
.${this.pageSeparatorClass} {
  position: relative !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  margin: ${this.getMargin()} !important;
  padding: 4px 0;
  width: 100% !important;
  max-width: 100% !important;
  min-width: 100% !important;
  background: var(${this.themeVarService.search.resultItem.background}) !important;
  color: var(${this.themeVarService.default.text.secondary}) !important;
  border-radius: 9999px !important;
  overflow: hidden !important; /* 隐藏溢出的进度条部分 */
  text-align: center;
  transition: all 0.3s ease !important;
  ${this.configService.getPageLayoutFixStyle()}
  
  &.${this.batchActiveClass} {
     &::after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 0;
      width: var(--progress-percentage, 0%);
      height: 2px;
      background: linear-gradient(90deg, #4CAF50, #45a049);
      transition: width 0.3s ease;
    }
    
    /* 不同进度状态的颜色 */
    &.progress-0::after {
      background: #e0e0e0;
      opacity: 0.3;
    }
    
    &.progress-25::after {
      background: linear-gradient(90deg, #ff9800, #ffb74d);
    }
    
    &.progress-50::after {
      background: linear-gradient(90deg, #ff9800, #4CAF50);
    }
    
    &.progress-75::after {
      background: linear-gradient(90deg, #4CAF50, #45a049);
    }
    
    &.progress-100::after {
      background: linear-gradient(90deg, #4CAF50, #2e7d32);
      animation: pulse ${this.hideProgressDelay}s infinite;
    }
  
    .page-link.mbf-page-all {
      &::after {
        position: absolute;
        content: attr(data-progress);
        left: calc(50% + 12px); /* 调整位置，避免与图标重叠 */
        top: 50%;
        transform: translateY(-50%);
        padding: 2px 6px;
        background: rgba(0, 0, 0, 0.8);
        color: white;
        border-radius: 3px;
        font-size: 10px;
        font-weight: bold;
        white-space: nowrap;
        opacity: 0;
        transition: all 0.3s ease;
        pointer-events: none;
        vertical-align: middle;
      }
      
      &.show-progress::after {
        opacity: 1;
      }
    }
  }
  
  /* 分页导航样式 */
  .mbf-page-nav {
    display: inline-flex;
    gap: ${this.themeVarService.search.resultItem.gap};
    align-items: center;
  }
  
  .mbf-page-scroll {
    position: relative;
    margin-right: -${this.themeVarService.search.resultItem.gap} !important;
    
    &::before {
      ${this.stylesService.inlinePseudo.iconMask({
        backgroundImageId: ICON_IDS.interface.pageScrollLoad,
        color: ICON_COLOR.active,
      })}
    }
    
    &.disabled::before {
      ${this.stylesService.inlinePseudo.setIconMask({
        iconId: ICON_IDS.interface.pageNoScrollLoad,
        color: ICON_COLOR.disabled,
      })}
    }
  }
  
  .page-link {
    position: relative;
    
    &:not(.mbf-page-all)::before {
      ${this.stylesService.inlinePseudo.icon()}
    }
    
    &.mbf-page-top::before {
      background-image: var(${this.themeVarService.generateIcon(ICON_IDS.interface.pageTop)}) !important;
    }
    &.mbf-page-prev::before {
      background-image: var(${this.themeVarService.generateIcon(ICON_IDS.interface.pagePrev)}) !important;
    }
    &.mbf-page-next::before {
      background-image: var(${this.themeVarService.generateIcon(ICON_IDS.interface.pageNext)}) !important;
    }
    &.mbf-page-end::before {
      background-image: var(${this.themeVarService.generateIcon(ICON_IDS.interface.pageEnd)}) !important;
    }
    &.mbf-page-more::before {
      background-image: var(${this.themeVarService.generateIcon(ICON_IDS.interface.pageMore)}) !important;
    }
    &.mbf-page-all { 
      &::before {
        ${this.stylesService.inlinePseudo.iconMask({ backgroundImageId: ICON_IDS.interface.pageAll })}
      }
      
      &.${IPaginationBatchLoadType.Custom}::before {
        ${this.stylesService.inlinePseudo.setIconMask({ iconId: ICON_IDS.interface.pageBatch })}
      }
    }
  }
  
  &.${this.batchActiveClass} .page-link.mbf-page-all::before {
    ${this.stylesService.inlinePseudo.setIconMask({
      iconId: ICON_IDS.interface.pageCancel,
      color: ICON_COLOR.hover,
    })}
  }
}

${this.messageAlert.styles(this.indicatorId)}
    `
  }
}
